home *** CD-ROM | disk | FTP | other *** search
/ The PC-SIG Library 10 / The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso / PC_SIGCD / 22 / 9 / DISK2290.ZIP / NG_SPLIT.ZIP / NG_SPLIT.C next >
C/C++ Source or Header  |  1988-08-12  |  20KB  |  697 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /*    ng_split - splits Norton Guides database into components    */
  4. /*                                    */
  5. /************************************************************************/
  6. /*                                    */
  7. /*    ng_split, Copyright (C) 1988, by John C. Gordon            */
  8. /*    Norton Guides Splitter, 12 August 1988, ALL RIGHTS RESERVED    */
  9. /*                                    */
  10. /*    This program is meant for those of us who bought the Norton    */
  11. /*    Guides and were disappointed by the fact that we couldn't    */
  12. /*    modify the databases provided for our own purposes (by making    */
  13. /*    the fatal assumption that "customizing the Guides" included    */
  14. /*    the ability to customize the published databases).        */
  15. /*                                    */
  16. /*    I have been able to take the databases provided in the Guides,    */
  17. /*    "un-compile" (split) them into their component parts, and    */
  18. /*    then re-compile them back into a database using the NGC and    */
  19. /*    NGML utilities provided with the Guides.  The resulting        */
  20. /*    database is identical to the original using DOS 'comp'        */
  21. /*    (except for a six-character difference in the Microsoft C    */
  22. /*    database, which does not affect execution).            */
  23. /*                                    */
  24. /*    I have tested this program on the Norton Guides for Turbo C    */
  25. /*    Microsoft C.  Others have tested it on the other published    */
  26. /*    databases and some public domain ones.  If you find that it    */
  27. /*    does not work for some database, I will be glad to look at    */
  28. /*    the code to see if I can get it to work.  I will need a copy    */
  29. /*    of the database file, however (only for debugging - the        */
  30. /*    disk(s) will be returned with a copy of the new program).    */
  31. /*                                    */
  32. /*    There are some funny file formats possible which NG_SPLIT    */
  33. /*    doesn't handle right now.  They will be corrected in V2.0 in    */
  34. /*    a couple of months.  They do not appear in any of Norton's    */
  35. /*    databases (as far as I know), but they can be created by the    */
  36. /*    NG software.  Please send me a copy of anything that NG_SPLIT    */
  37. /*    can't handle, so I can make sure that everything is covered.    */
  38. /*    Included in V2 or V3 will be a utility to re-write the funny    */
  39. /*    source code into something more reasonable, since usually the    */
  40. /*    strange formats mess up the operation of the grey + key.    */
  41. /*                                    */
  42. /*    If you like this program and would like to see more like    */
  43. /*    it, please contribute whatever you think this program is    */
  44. /*    worth to you (recommended $5 or $10).  Thank you.        */
  45. /*                                    */
  46. /*            John C. Gordon                    */
  47. /*            Post Office Box 25107                */
  48. /*            Alexandria, VA  22313-5107            */
  49. /*                                    */
  50. /*            Home phone : (703) 528-2205            */
  51. /*                                    */
  52. /************************************************************************/
  53.  
  54. /************************************************************************/
  55. /*                                    */
  56. /*    ng_split        Version 1.2        12 August 1988    */
  57. /*                                    */
  58. /*    Purpose:    Split a Norton Guides .ng database into        */
  59. /*            its original component source files        */
  60. /*                                    */
  61. /*    Syntax:        ng_split db_name                */
  62. /*    Where:        'db_name' = the name of the Norton Guides    */
  63. /*            database (with or without the .ng suffix)    */
  64. /*                                    */
  65. /*    Restrictions:    1)  The NG database must be located in your    */
  66. /*                current working directory.            */
  67. /*            2)  The database must not be "active" when    */
  68. /*                you run ng_split.  You must either        */
  69. /*                uninstall the Guides or copy the database    */
  70. /*                to a different (work) directory first.    */
  71. /*            3)  Due to the intensive character I/O, you    */
  72. /*                should run from your RAMdisk, if possible.    */
  73. /*                                    */
  74. /*    Remarks:    ng_split will create several files in your    */
  75. /*            current working directory :            */
  76. /*                                    */
  77. /*        'db_name':    the menu link control file        */
  78. /*        'db_name'.bat:    a batch file containing the commands    */
  79. /*            to re-create the database            */
  80. /*        'dbxx'_000:    the individual source data files are    */
  81. /*            named 'dbxx'_000 through 'dbxx'_999, depending    */
  82. /*            on how many files are needed.  Note : 'dbxx'    */
  83. /*            is the first four characters of 'db_name'.    */
  84. /*        temp:    a temporary file which is deleted on exit    */
  85. /*                                    */
  86. /*    For example : if you are splitting the Turbo C database tc.ng,    */
  87. /*        you would use the command:    ng_split tc        */
  88. /*        which would create files:    tc            */
  89. /*                        tc.bat            */
  90. /*                        tc_000 through tc_011    */
  91. /*                        temp (deleted)        */
  92. /*                                    */
  93. /*    Change history:                            */
  94. /*        V 1.0 - 17 June 88 - original program            */
  95. /*        V 1.1 - 18 July 88 - allow databases with names longer    */
  96. /*                than six characters or with more than    */
  97. /*                26 source files and update docs        */
  98. /*        V 1.2 - 12 August 88 - fix bug with !short with no data    */
  99. /*                following it and !file.  also added    */
  100. /*                status lines and better error messages    */
  101. /*                                    */
  102. /************************************************************************/
  103.  
  104. /************************************************************************/
  105. /*                                    */
  106. /*    Hints on interpreting error messages :                */
  107. /*                                    */
  108. /*    In general, all error messages indicate that NG_SPLIT was    */
  109. /*    unable to successfully split your database.  In those cases,    */
  110. /*    I would appreciate it if you could send me a copy of the    */
  111. /*    database, so I can correct the program.  There are two error    */
  112. /*    messages, however, which I can do nothing about :        */
  113. /*                                    */
  114. /*    Write error - possibly out of disk space            */
  115. /*        - this indicates that either you are out of space    */
  116. /*          OR your directory cannot hold any more files.        */
  117. /*                                    */
  118. /*    WARNING - Database error                    */
  119. /*        - this one comes up if there is an error in the        */
  120. /*          database itself.  It occurs when it is trying to    */
  121. /*          locate a !seealso segment and the database contains    */
  122. /*          an illegal address.  You can verify this by looking    */
  123. /*          at the output file which contains the error and    */
  124. /*          searching for the string :        _???.ngo:    */
  125. /*          Make note of the name of the faulty !seealso clause    */
  126. /*          ( the name in quotes after the colon ) and the name    */
  127. /*          of the !short section which contains it ( backward    */
  128. /*          search for !short: ).  Next, look at the menu link    */
  129. /*          control file ( same name as the database, but without    */
  130. /*          the .ng suffix ) and look for the name of the output    */
  131. /*          file which contained the error.  Make note of the    */
  132. /*          menu heading and the menu item which corresponds to    */
  133. /*          that file.  Now, bring up the database and find the    */
  134. /*          menu heading and menu item.  Then, look up the name    */
  135. /*          of the !short item you located before.  You will    */
  136. /*          notice that it has a !seealso item with the faulty    */
  137. /*          clause name.  If you try to select that !seealso    */
  138. /*          clause, nothing will happen.  I don't know why this    */
  139. /*          happens and have only seen it happen in one database    */
  140. /*          If I get several different databases with this    */
  141. /*          problem, I may be able to find a pattern and find a    */
  142. /*          way to correct the database and the source files.    */
  143. /*                                    */
  144. /*          Of course, the above instructions to verify the    */
  145. /*          database error are a little more complicated if the    */
  146. /*          error is in a !file instead of a !short called from    */
  147. /*          the menu, but its the same principle - its just a    */
  148. /*          little more work to find out which !short the error    */
  149. /*          is in.                        */
  150. /*                                    */
  151. /************************************************************************/
  152.  
  153. #include <stdio.h>
  154. #include <io.h>
  155.  
  156. /* GLOBAL VARIABLES  - declared globally so functions below can get    */
  157. /*            to them without making them parameters        */
  158.  
  159. long i;            /* character count */
  160. FILE *in;        /* input stream to get characters from */
  161. char name_long[9];    /* incoming file name stub */
  162. char temp_name[9];    /* temp area for make_fn to return filename into */
  163.  
  164. char *make_fn (fnum)    /* creates temp_name from name_long & fnum */
  165. int fnum;
  166. {
  167.     char j_str[4];
  168.     int j;
  169.  
  170.     strcpy (temp_name, name_long);
  171.     j = strlen (temp_name); if (j > 4) j = 4;
  172.     temp_name[j] = '_'; temp_name[j+1] = '\0';
  173.     if (fnum < 0) strcat (temp_name, "???");
  174.     else
  175.     {
  176.         if (fnum <= 9) strcat (temp_name, "00");
  177.         else if (fnum <= 99) strcat (temp_name, "0");
  178.         itoa (fnum, j_str, 10);
  179.         strcat (temp_name, j_str);
  180.     }
  181.  
  182.     return (temp_name);
  183. }
  184.  
  185. get_n (n)        /* get <n> characters */
  186. int n;
  187. {
  188.     while (n-- > 0) { getc (in); i++; }
  189.     return;
  190. }
  191.  
  192. get_cvt ()        /* get one decoded (XOR 26) character */
  193. {
  194.     int n;
  195.  
  196.     n = getc (in); i++;
  197.     if ((n % 32) >= 16) n = n - 16; else n = n + 16;
  198.     if ((n % 16) >= 8)  n = n - 8;  else n = n + 8;
  199.     if ((n % 4)  >= 2)  n = n - 2;  else n = n + 2;
  200.     return (n);
  201. }
  202.  
  203. get_2num ()        /* get decoded two-byte integer */
  204. {
  205.     int n;
  206.  
  207.     n = get_cvt () + (get_cvt () * 256);
  208.     return (n);
  209. }
  210.  
  211. long get_4addr ()    /* get decoded four-byte address */
  212. {
  213.     long n;
  214.  
  215.     n  =  (long) get_cvt ();
  216.     n += ((long) get_cvt () * 256L);
  217.     n += ((long) get_cvt () * 256L * 256L);
  218.     n += ((long) get_cvt () * 256L * 256L * 256L);
  219.     return (n);
  220. }
  221.  
  222. /* THE MAIN PROCEDURE */
  223.  
  224. main (argc, argv)
  225. int argc;
  226. char *argv[];
  227. {
  228.     int n, pn, j, name_out_j, ct, items, z, addr_ct, cp, zz_ct;
  229.     int errno, zlen, tlen, see_ct, m, m1, m2, temp_file, temp_ch;
  230.     int save_ch, orig_addr_ct, addr_ct_z, zz_ct_i;
  231.     int zc[500];
  232.  
  233.     long addr[500], seealso[500], zz[500];
  234.  
  235.     char name_in[13], name_out[13], name_bat[13];
  236.  
  237.     FILE *out, *bat, *temp;
  238.  
  239. /* print credits */
  240.  
  241.     printf ("\nNG_SPLIT, Copyright (C) 1988, by John C. Gordon\n");
  242.     printf ("Norton Guides Database Splitter, 12 August 1988, ");
  243.     printf ("ALL RIGHTS RESERVED\n\n");
  244.  
  245. /* check to see if database name was passed in */
  246.  
  247.     if (argc < 2)
  248.         { printf ("You must supply a database name !\n"); exit (1); }
  249.  
  250. /* set up file names */
  251.  
  252.     j = 0;
  253.     while (*argv[1] != '\0' && *argv[1] != '.')
  254.         name_long [j++] = *argv[1]++;
  255.     name_long [j] = '\0';
  256.  
  257.     strcpy (name_in,  name_long); strcat (name_in,  ".ng");
  258.     strcpy (name_bat, name_long); strcat (name_bat, ".bat");
  259.     strcpy (name_out, name_long); name_out_j = 0;
  260.  
  261.     if ((in = fopen (name_in, "rb")) == NULL)
  262.         { printf ("cannot read '%s'\n", name_in); goto close; }
  263.     if ((bat = fopen (name_bat, "wb")) == NULL)
  264.         { printf ("cannot write to '%s'\n", name_bat); goto close; }
  265.     if ((out = fopen (name_out, "wb")) == NULL)
  266.         { printf ("cannot write to '%s'\n", name_out); goto close; }
  267.  
  268. /* load all addresses */
  269.  
  270.     rewind (in);
  271.     addr_ct = 0;
  272.  
  273.     get_n (378);
  274.     i = 377;
  275.     n = get_cvt ();
  276.     while (n == 2)
  277.     {
  278.         get_n (3);
  279.         items = get_2num ();
  280.         get_n (20);
  281.         for (ct = 1; ct < items; ct++) addr[addr_ct++] = get_4addr ();
  282.         get_n (items * 8);
  283.         n = get_cvt ();
  284.         while (n != 0) n = get_cvt ();
  285.         for (ct = 1; ct < items; ct++)
  286.         {
  287.             n = get_cvt ();
  288.             while (n != 0) n = get_cvt ();
  289.         }
  290.         get_n (1);
  291.         n = get_cvt ();
  292.     }
  293.  
  294. /* now we have the "normal" addr[]s - get the additional ones */
  295.  
  296.     if (i != addr[0]) { errno = 1; goto error; }
  297.  
  298.     printf ("    detected %3d original source files\n", addr_ct);
  299.     printf ("    ... searching for additional files\n");
  300.  
  301.     orig_addr_ct = addr_ct;
  302.     addr[addr_ct] = (long) filelength (fileno (in));
  303.  
  304.     for (z = 1; z <= addr_ct; z++)
  305.     {
  306.         temp_file = 0;
  307.         while (i < addr[z] && !feof (in))
  308.         {
  309.             if (n == 0)
  310.             {
  311.                 get_n (1);
  312.                 tlen = get_2num ();
  313.                 zlen = get_2num ();
  314.                 get_n (20);
  315.                 for (zz_ct = 0; zz_ct < zlen; zz_ct++)
  316.                     { get_n (2); zz[zz_ct] = get_4addr (); }
  317.                 n = get_cvt ();
  318.                 zz_ct = 0;
  319.                 if    (zz[zz_ct] < 0L)      zc[zz_ct] = ' ';
  320.                 else if (zz[zz_ct] < addr[z]) zc[zz_ct] = '!';
  321.                 else
  322.                 {
  323.                     zc[zz_ct] = '!' + addr_ct;
  324.                     addr_ct++;
  325.                     addr[addr_ct] = addr[addr_ct - 1];
  326.                     addr[addr_ct - 1] = zz[zz_ct];
  327.                     printf ("    ... detected file %d\n",
  328.                             addr_ct);
  329.                 }
  330.  
  331.     for (ct = zlen * 6; ct < tlen - 1; ct++)
  332.     {
  333.         if (n == 0)
  334.         {
  335.             zz_ct++;
  336.             if    (zz[zz_ct] < 0L)    zc[zz_ct] = ' ';
  337.             else if (zz[zz_ct] < addr[z])    zc[zz_ct] = '!';
  338.             else
  339.             {
  340.                 zc[zz_ct] = '!' + addr_ct;
  341.                 addr_ct++;
  342.                 addr[addr_ct] = addr[addr_ct - 1];
  343.                 addr[addr_ct - 1] = zz[zz_ct];
  344.                 printf ("    ... detected file %d\n", addr_ct);
  345.             }
  346.         }
  347.         else if (n == 255) { n = get_cvt (); ct++; }
  348.         n = get_cvt ();
  349.     }
  350.  
  351.                 zz_ct_i = 0;
  352.                 temp_file = 1;
  353.                 n = get_cvt ();
  354.                 if (feof (in)) goto tn;
  355.                 else if (n != 1) { errno = 2; goto error; }
  356.             }
  357.  
  358.             else if (n == 1)
  359.             {
  360. tn:
  361.                 if (temp_file == 1)
  362.                 {
  363.                     save_ch = zc[zz_ct_i++];
  364.                     if (save_ch == ' ') goto el;
  365.                     if (save_ch > '!') goto el;
  366.                 }
  367.                 get_n (1);
  368.                 zlen = get_2num ();
  369.                 get_n (2);
  370.                 tlen = get_2num ();
  371.                 if (tlen == 0) tlen = zlen;
  372.                 get_n (18);
  373.                 n = get_cvt ();
  374.                 for (ct = 0; ct < tlen; ct++)
  375.                 {
  376.                     if (n == 255)
  377.                         { n = get_cvt (); ct++; }
  378.                     n = get_cvt ();
  379.                 }
  380.                 if (tlen != zlen)
  381.                 {
  382.                     see_ct = n;
  383.                     zlen = zlen - tlen - (see_ct * 4) - 2 - 2;
  384.                     get_n (1);
  385.                     if (see_ct != 0)
  386.                     {
  387.                         for (ct = 0; ct < see_ct; ct++)
  388.                             get_n (4);
  389.                         get_n (zlen + 1);
  390.                     }
  391.                     get_n (1);
  392.                     n = get_cvt ();
  393.                 }
  394. el:
  395.                 if (temp_file == 1 && zz_ct_i <= zz_ct) goto tn;
  396.             }
  397.             else { errno = 3; goto error; }
  398.         }
  399.         if (z < addr_ct) if (i > addr[z]) { errno = 4; goto error; }
  400.         if (z == addr_ct) if (!feof (in)) { errno = 5; goto error; }
  401.         if (temp_file == 1)
  402.             if (zz_ct_i <= zz_ct) { errno = 6; goto error; }
  403.     }
  404.  
  405.     rewind (in);    /* reset file for real reads */
  406.  
  407. /* read the header */
  408.  
  409.     for (i = 0; i < 8; i++) n = getc (in);
  410.     fprintf (out, "!name: ");
  411.     for (i = 0; i < 40; i++) if ((n = getc (in)) != 0) putc (n, out);
  412.     fprintf (out, "\r\n!credits:\r\n");
  413.     for (j = 0; j < 5; j++)
  414.     {
  415.         for (i = 0; i < 66; i++)
  416.             if ((n = getc (in)) != 0) putc (n, out);
  417.         fprintf (out, "\r\n");
  418.     }
  419.  
  420. /* read the menu sections */
  421.  
  422.     i = 377; j = 0;
  423.     n = get_cvt ();
  424.     while (n == 2)
  425.     {
  426.         get_n (1);
  427.         get_n (2);    /* len = get_2num (); */
  428.         items = get_2num ();
  429.  
  430.         get_n (20);
  431.         for (ct = 1; ct < items; ct++) get_n (4);
  432.         get_n (items * 8);
  433.  
  434.         fprintf (out, "\r\n!menu: ");
  435.         n = get_cvt ();
  436.         while (n != 0) { putc (n, out); n = get_cvt (); }
  437.         fprintf (out, "\r\n");
  438.         for (ct = 1; ct < items; ct++)
  439.         {
  440.             fprintf (out, "       ");
  441.             cp = 7;
  442.             n = get_cvt ();
  443.             while (n != 0) { putc (n, out); cp++; n = get_cvt (); }
  444.             while (cp++ < 40) putc (' ', out);
  445.             fprintf (out, " %s.ngo", make_fn (j));
  446.             fprintf (bat, "ngc %s\r\n", make_fn (j));
  447.             j++;
  448.             fprintf (out, "\r\n");
  449.         }
  450.         get_n (1);
  451.         n = get_cvt ();
  452.     }
  453.  
  454. /* now < i > = the address of the byte just read into < n > = first NGO */
  455.  
  456.     if (i != addr[0]) { errno = 1; goto error; }
  457.  
  458.     printf ("\nNG_SPLIT detected %d + %d source files ...\n\n",
  459.             orig_addr_ct, addr_ct - orig_addr_ct);
  460.     printf ("    writing batch & menu file...");
  461.  
  462.     addr_ct_z = orig_addr_ct;        
  463.     for (z = 1; z <= addr_ct; z++)
  464.     {
  465.         fclose (out);
  466.         strcpy (name_out, make_fn (name_out_j));
  467.         if ((out = fopen (name_out, "wb")) == NULL)
  468.         {
  469.             printf ("cannot write to '%s'\n", name_out);
  470.             goto close;
  471.         }
  472.         name_out_j++;
  473.         printf (" %2ld%% complete\n",
  474.             100L * (long) addr[z - 1] / (long) addr[addr_ct]);
  475.         if (z == orig_addr_ct + 1)
  476.             printf ("\n    ***  ADDITIONAL SOURCE FILES  ***\n\n");
  477.         printf ("    writing to file %8s ...", name_out);
  478.  
  479.         temp_file = 0;
  480.  
  481.         while (i < addr[z] && !feof (in))
  482.         {
  483.  
  484. /* the following pages are un-tabbed three tab stops for readability */
  485.  
  486. if (n == 0)
  487. {
  488.     if ((temp = fopen ("temp", "wb")) == NULL)
  489.     {
  490.         printf ("cannot write to 'temp'\n");
  491.         goto close;
  492.     }
  493.     get_n (1);
  494.     tlen = get_2num ();
  495.     zlen = get_2num ();
  496.     get_n (20);
  497.     for (zz_ct = 0; zz_ct < zlen; zz_ct++)
  498.         { get_n (2); zz[zz_ct] = get_4addr (); }
  499.     n = get_cvt ();
  500.     zz_ct = 0;
  501.     if    (zz[zz_ct] < 0L)      fprintf (temp, " short:");
  502.     else if (zz[zz_ct] < addr[z]) fprintf (temp, "!short:");
  503.     else
  504.     {
  505.         fprintf (temp, "%cshort:", '!' + addr_ct_z);
  506.         fprintf (bat, "ngc %s\r\n", make_fn (addr_ct_z));
  507.         addr_ct_z++;
  508.     }
  509.  
  510.     for (ct = zlen * 6; ct < tlen - 1; ct++)
  511.     {
  512.         if (n == 0)
  513.         {
  514.             zz_ct++;
  515.             if    (zz[zz_ct] < 0L)
  516.                 fprintf (temp, "\r\n short:");
  517.             else if (zz[zz_ct] < addr[z])
  518.                 fprintf (temp, "\r\n!short:");
  519.             else
  520.             {
  521.                 fprintf (temp, "\r\n%cshort:", '!' + addr_ct_z);
  522.                 fprintf (bat, "ngc %s\r\n", make_fn (addr_ct_z));
  523.                 addr_ct_z++;
  524.             }
  525.         }
  526.         else if (n != 255) putc (n, temp);
  527.         else
  528.         {
  529.             n = get_cvt (); ct++;
  530.             while (n-- > 0) putc (' ', temp);
  531.         }
  532.         n = get_cvt ();
  533.     }
  534.     fprintf (temp, "\r\n");
  535.     fclose (temp);
  536.     if ((temp = fopen ("temp", "rb")) == NULL)
  537.     {
  538.         printf ("cannot read 'temp'\n");
  539.         exit (1);
  540.     }
  541.     temp_ch = getc (temp);
  542.     temp_file = 1;
  543.     n = get_cvt ();
  544.     if (feof (in)) goto try_next;
  545.     else if (n != 1) { errno = 2; goto error; }
  546. }
  547.  
  548. else if (n == 1)
  549. {
  550. try_next:
  551.     if (temp_file == 1)
  552.     {
  553.         save_ch = temp_ch;
  554.         temp_ch = '!';
  555.         while (temp_ch != '\r')
  556.         {
  557.             putc (temp_ch, out);
  558.             temp_ch = getc (temp);
  559.         }
  560.         temp_ch = getc (temp);
  561.         temp_ch = getc (temp);
  562.         fprintf (out, "\r\n");
  563.         if (save_ch == ' ') goto end_loop;
  564.         else if (save_ch > '!')
  565.         {
  566.             save_ch -= '!';
  567.             fprintf (out, "!file: %s.ngo\r\n", make_fn (save_ch));
  568.             goto end_loop;
  569.         }
  570.     }
  571.     get_n (1);
  572.     zlen = get_2num ();
  573.     get_n (2);
  574.     tlen = get_2num ();
  575.     if (tlen == 0) tlen = zlen;
  576.     get_n (18);
  577.     n = get_cvt ();
  578.     pn = 0;
  579.     for (ct = 0; ct < tlen; ct++)
  580.     {
  581.         if (n == 0)
  582.         {
  583.             if (pn == 0) putc (' ', out);
  584.             fprintf (out, "\r\n");
  585.         }
  586.         else if (n != 255) putc (n, out);
  587.         else
  588.         {
  589.             n = get_cvt (); ct++;
  590.             while (n-- > 0) putc (' ', out);
  591.         }
  592.         pn = n; n = get_cvt ();
  593.     }
  594.  
  595.     if (tlen != zlen)
  596.     {
  597.         see_ct = n;
  598.         zlen = zlen - tlen - (see_ct * 4) - 2 - 2;
  599.         get_n (1);
  600.         fprintf (out, "!seealso: ");
  601.         if (see_ct != 0)
  602.         {
  603.             for (ct = 0; ct < see_ct; ct++)
  604.                 seealso[ct] = get_4addr ();
  605.             m1 = 0;
  606.             for (m2 = addr_ct - 1; seealso[m1] < addr[m2]; m2--) ;
  607.             if (m2 < 0)
  608.                 printf (" WARNING - Database error ! ...");
  609.             if (name_out_j != m2 + 1)
  610.                 fprintf (out, "%s.ngo:", make_fn (m2));
  611.             fprintf (out, "\"");
  612.             n = get_cvt ();
  613.             for (ct = 0; ct < zlen; ct++)
  614.             {
  615.                 if (n == 0)
  616.                 {
  617.                     m1++;
  618.                     for (m2 = addr_ct - 1;
  619.                         seealso[m1] < addr[m2]; m2--) ;
  620.                     fprintf (out, "\" ");
  621.                     if (m2 < 0)
  622.                     {
  623.                         printf (" WARNING - ");
  624.                         printf ("Database error ! ...");
  625.                     }
  626.                     if (name_out_j != m2 + 1)
  627.                         fprintf (out, "%s.ngo:",
  628.                             make_fn (m2));
  629.                     fprintf (out, "\"");
  630.                 }
  631.                 else putc (n, out);
  632.                 n = get_cvt ();
  633.             }
  634.             fprintf (out, "\"");
  635.         }
  636.         fprintf (out, "\r\n");
  637.         get_n (1);
  638.         n = get_cvt ();
  639.     }
  640. end_loop:
  641.     if (temp_file == 1 && !feof (temp)) goto try_next;
  642. }
  643. else { errno = 3; goto error; }
  644.  
  645. /* normal tabbing resumes on this page */
  646.  
  647.         }
  648.         if (z < addr_ct) if (i > addr[z]) { errno = 4; goto error; }
  649.         if (z == addr_ct) if (!feof (in)) { errno = 5; goto error; }
  650.         if (temp_file == 1)
  651.         {
  652.             if (!feof (temp)) { errno = 6; goto error; }
  653.             fclose (temp);
  654.         }
  655.     }
  656.     if (ferror (out)) { errno = 7; goto error; }
  657.     printf ("\n\nSUCCESSFUL - Created %d source files !\n", addr_ct);
  658.     goto close;
  659.  
  660. error:
  661.     printf ("\n\nERROR %d !  ", errno);
  662.     switch (errno)
  663.     {
  664.         case 1:    printf ("Header is ");
  665.             if (i > addr[0])
  666.                 printf ("%ld bytes too long",  i - addr[0]);
  667.             else    printf ("%ld bytes too short", addr[0] - i);
  668.             break;
  669.         case 2:    printf ("Section # 0 is not followed by # 1 ( %d )", n);
  670.             break;
  671.         case 3:    printf ("Cannot recognize section # %d", n);
  672.             break;
  673.         case 4:    printf ("Section is ");
  674.             if (i > addr[z])
  675.                 printf ("%ld bytes too long",  i - addr[z]);
  676.             else    printf ("%ld bytes too short", addr[z] - i);
  677.             break;
  678.         case 5:    printf ("Did not reach EOF on input database");
  679.             break;
  680.         case 6:    printf ("Did not reach EOF on 'temp' file");
  681.             break;
  682.         case 7:    printf ("Write error - possibly out of disk space");
  683.     }
  684.     printf ("\n\n");
  685.     printf ("    Byte number = %ld\n", i);
  686.     printf ("    EOF = %ld\n\n", addr[addr_ct]);
  687.     for (z = 0; z < addr_ct; z++)
  688.         printf ("    addr[%d] = %ld\n", z, addr[z]);
  689.  
  690. close:
  691.     printf ("\n");
  692.     fprintf (bat, "ngml %s\r\n", name_long);
  693.     fcloseall ();
  694.     unlink ("temp");
  695.     exit (0);
  696. }
  697.